﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Data;
using Croxweb.Leuphana.Services.MyStudyService;
using Croxweb.Leuphana.Services.StorageService;
using System.Windows;
using System.Windows.Threading;


namespace Croxweb.Leuphana.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        private readonly IMyStudyService service;
        private readonly ISettingStore config;

        private CollectionViewSource nextAppointmentsViewSource = new CollectionViewSource();
        private CollectionViewSource messageViewSource = new CollectionViewSource();

        private ObservableCollection<AppointmentViewModel> appointments;
        private ObservableCollection<MessageViewModel> messages;

        private DateTime nextAppointmentsDay;

        private Boolean isSynchronizing = false;
        private Boolean isLoggedIn = false;
        private Boolean isDataLoaded = false;
        private Boolean isUpdated = false;


        // Constructor.
        public MainViewModel(IMyStudyService service, ISettingStore config)
        {
            this.service = service;
            this.config = config;

            IsLoggedIn = config.ValidatedUser;
        }


        // Status properties.
        public Boolean IsSynchronizing
        {
            get { return isSynchronizing; }
            set
            {
                isSynchronizing = value;
                NotifyPropertyChanged("IsSynchronizing");
            }
        }
        public Boolean IsLoggedIn
        {
            get { return isLoggedIn; }
            set
            {
                isLoggedIn = value;
                NotifyPropertyChanged("IsLoggedIn");
            }
        }
        public Boolean IsDataLoaded
        {
            get { return isDataLoaded; }
            private set
            {
                isDataLoaded = value;
                NotifyPropertyChanged("IsDataLoaded");
            }
        }
        public Boolean IsUpdated
        {
            get { return isUpdated; }
            private set
            {
                isUpdated = value;
                NotifyPropertyChanged("IsUpdated");
            }
        }

        public String NextAppointmentsDay
        {
            get
            {
                if (appointments.Count > 0)
                {
                    if (nextAppointmentsDay < DateTime.Today.AddDays(1))
                    {
                        return "Heute";
                    }

                    if (nextAppointmentsDay < DateTime.Today.AddDays(2))
                    {
                        return "Morgen";
                    }

                    return nextAppointmentsDay.ToLongDateString();
                }

                return "Keine Termine in den nächsten 14 Tagen.";
            }
        }


        // List properties.
        public ICollectionView NextAppointments { get { return nextAppointmentsViewSource.View; } }
        public ICollectionView NewMessages { get { return messageViewSource.View; } }


        // Activities.
        public void Refresh()
        {
            if (!isDataLoaded)
            {
                IsDataLoaded = true;

                refreshSchedule();
                refreshMessages();

                // Update all properties.
                NotifyPropertyChanged(String.Empty);
            }
        }

        private void refreshSchedule()
        {
            appointments = new ObservableCollection<AppointmentViewModel>();

            NextEventList nextAppointments = service.GetNextAppointments(5);

            nextAppointments.ForEach((appointment) =>
            {
                appointments.Add(new AppointmentViewModel(appointment));
            });

            nextAppointmentsDay = nextAppointments.StartDate;

            nextAppointmentsViewSource = new CollectionViewSource() { Source = appointments };
            nextAppointmentsViewSource.SortDescriptions.Add(new SortDescription("StartTime", ListSortDirection.Ascending));
            nextAppointmentsViewSource.View.MoveCurrentToPosition(-1);

            // Notify updates.
            NotifyPropertyChanged("NextAppointments");
            NotifyPropertyChanged("NextAppointmentDay");
        }
        private void refreshMessages()
        {
            messages = new ObservableCollection<MessageViewModel>();

            service.GetLatestMessages(5).ToList().ForEach((message) =>
            {
                messages.Add(new MessageViewModel(message));
            });

            messageViewSource = new CollectionViewSource() { Source = messages };
            messageViewSource.View.MoveCurrentToPosition(-1);

            // Notify updates.
            NotifyPropertyChanged("NewMessages");
        }

        public void SyncSchedule()
        {
            if (!isSynchronizing)
            {
                IsSynchronizing = true;

                service.SynchronizeSchedule((lectures) =>
                {
                    refreshSchedule();

                    IsSynchronizing = false;
                });
            }
        }
        public void SyncMessages()
        {
            if (!isSynchronizing)
            {
                IsSynchronizing = true;

                service.SynchronizeMessages((newMessages) =>
                {
                    Dispatcher dispatcher = Deployment.Current.Dispatcher;
                    BackgroundWorker worker = new BackgroundWorker();

                    worker.DoWork += (o, e) =>
                    {
                        messages = new ObservableCollection<MessageViewModel>();

                        service.GetLatestMessages(5).ToList().ForEach((message) =>
                        {
                            messages.Add(new MessageViewModel(message));
                        });

                        dispatcher.BeginInvoke(() =>
                        {
                            messageViewSource = new CollectionViewSource() { Source = messages };
                            messageViewSource.View.MoveCurrentToPosition(-1);

                            // Notify updates.
                            NotifyPropertyChanged("NewMessages");
                        });


                    };

                    worker.RunWorkerAsync();

                    IsSynchronizing = false;
                    IsUpdated = true;
                });
            }
        }

        public void Login(String username, String password)
        {

            IsSynchronizing = true;

            service.Authorize(password, (authResult, token) =>
                {
                    switch (authResult)
                    {
                        // Successfull authorization. Download schedule.
                        case MyStudyResult.Success:
                            config.Username = username;
                            config.Password = token;

                            // Configure service.
                            MyStudyCredentials credentials = new MyStudyCredentials(username, token, config.Semester);
                            service.SetCredentials(credentials);

                            service.SynchronizeSchedule((result) =>
                            {
                                if (result == MyStudyResult.Success)
                                {
                                    refreshSchedule();

                                    config.ValidatedUser = true;
                                    IsLoggedIn = true;
                                }
                                else
                                {
                                    MessageBox.Show("Es ist ein Fehler aufgetreten. Bitte versuche es zu einem späteren Zeitpunkt erneut.", "Fehler", MessageBoxButton.OK);
                                }

                                IsSynchronizing = false;
                            });

                            break;

                        // Wrong username or password.
                        case MyStudyResult.AccessDenied:
                            MessageBox.Show("Benutzer und/oder Password waren falsch. Bitte versuche es erneut.", "Fehler", MessageBoxButton.OK);
                            IsSynchronizing = false;
                            break;

                        // No server connection.
                        case MyStudyResult.UnreachableServer:
                            MessageBox.Show("Der MyStudy-Service konnte nicht aufgerufen werden.\n\nWahrscheinlich fehlt dir das Leuphana-Sicherheitszertifikat für den Zugang.", "Fehler", MessageBoxButton.OK);
                            IsSynchronizing = false;
                            break;

                        case MyStudyResult.UnknownError:
                        default:
                            IsSynchronizing = false;
                            break;
                    }
                });
        }
        public void Logout()
        {
            config.Username = "";
            config.Password = "";
            config.Semester = "";
            config.ValidatedUser = false;

            IsLoggedIn = false;
        }
    }
}